﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Kugar.Core.BaseStruct;
using Kugar.Core.ExtMethod;
using Kugar.Core.Log;
using Kugar.Web.Wechat.Entities;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;

namespace Kugar.Web.Wechat
{
    public class WechatPayCallbackController : Controller
    {
        [HttpPost,Route("Core/MP/Pay/Notify")]
        public async Task<string> Notify([FromServices]IWechatPayHandler handler)
        {
            Request.EnableBuffering();
            Request.Body.Position = 0L;

            var content = Request.Body.ReadToEnd(Encoding.UTF8);
            try
            {
                

                WxPayData notifyData = new WxPayData();

                var xml = new XmlDocument();
                xml.LoadXml(content);
                
                try
                {
                    await handler.OnNotifyLog(xml);
                }
                catch (Exception e)
                {

                }
                
                XmlNode xmlNode = xml.FirstChild; //获取到根节点<xml>
                XmlNodeList nodes = xmlNode.ChildNodes;
                
                var tmp = nodes.AsEnumerable<XmlNode>();

                var returnCode = xmlNode.GetFirstNodeByTagName("return_code").InnerText;
                ResultReturn ret = null;
                if (returnCode.CompareTo("SUCCESS", true))
                {
                    var appID = xmlNode.GetFirstNodeByTagName("appid")?.InnerText;
                    var mchID = xmlNode.GetFirstNodeByTagName("mch_id")?.InnerText;

                    var info = await handler.WechatPayGetter(appID);// WechatPay.Default.OnPayKeyRequest(appID, mchID);

                    if (string.IsNullOrWhiteSpace(info.payKey))
                    {
                        throw new ArgumentNullException("payKey", "PayKeyRequest事件返回的paykey不能为空字符串");
                    }

                    var data = notifyData.FromXml(xml, info.payKey);

                    var openID = xmlNode.GetFirstNodeByTagName("openid")?.InnerText;

                    var attach = JObject.Parse(data["attach"].ToStringEx());
                    var state = attach.GetString("State");

                    try
                    {
                        var amount = (decimal) data["total_fee"].ToStringEx().ToInt() / 100;
                        var out_trade_no = xmlNode.GetFirstNodeByTagName("out_trade_no").InnerText;
                        var transaction_id = xmlNode.GetFirstNodeByTagName("transaction_id").InnerText;

                        ret=await handler.OnPaySuccessNotify(appID, mchID, openID, amount, out_trade_no, transaction_id,
                            state);
       
                    }
                    catch (Exception e)
                    {
                        LoggerManager.Default.Error("微支付回调:触发支付成功事件错误:",e);

                        ret=new FailResultReturn(e);
                    }
                    
                }
                else
                {
                    var msg = tmp.FirstOrDefault(x => x.Name == "return_msg")?.Value;
                    ret=await handler.OnPayFailNotify(msg, xml);
                }

                if (ret.IsSuccess)
                {
                    return
                        "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
                }
                else
                {
                    var str =
                        $"<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[{ret.Message}]]></return_msg></xml>";

                    return str;
                }
            }
            catch (Exception ex)
            {
                //若签名错误，则立即返回结果给微信支付后台
                //WxPayData res = new WxPayData();
                //res.SetValue("return_code", "FAIL");
                //res.SetValue("return_msg", ex.Message);
                //Log.Error(this.GetType().ToString(), "Sign check error : " + res.ToXml());
                //page.Response.Write(res.ToXml());
                //page.Response.End();

                var str =
                    $"<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[{ex.Message}]]></return_msg></xml>";

                return str;
            }
        }
    }
}